<template>
  <div id="viewport" data-type="viewport" class="holder">
    <div
      :style="{
        height: page.height + 'px',
        width: page.width + 'px',
        backgroundImage: 'url(' + backImg + ')',
      }"
      class="screen"
    >
      <!-- 组件 -->
      <component
        v-for="val in widgetStore"
        :is="val.type"
        :data-title="val.type"
        :class="{ active: widgetId === val.uuid }"
        :key="val.uuid"
        :val="val"
        :data-type="val.type"
        :data-uuid="val.uuid"
        class="layer"
        @change="(value) => (val.value = value)"
      ></component>

      <!-- 参考线 -->
      <!-- <ref /> -->

      <!-- 尺寸控制器 -->
      <control />
    </div>
  </div>
</template>

<script>
import control from "./size-control.vue";
import useMove from "../../mixins/move";
import {
  defineComponent,
  computed,
  getCurrentInstance,
  onMounted,
} from "vue-demi";
import { getVptd } from "../../utils/compat";

export default defineComponent({
  components: {
    control, // 尺寸控制
  },
  setup() {
    const instance = getCurrentInstance();
    const vptd = getVptd(instance);
    const page = computed(() => {
      return vptd.state.page;
    });
    const widgetStore = computed(() => {
      return vptd.state.page.tempItems;
    });
    const widgetId = computed(() => {
      return vptd.state.uuid;
    });
    const backImg = computed(() => {
      return vptd.state.page.imageUrl ? vptd.state.page.imageUrl : "";
    });
    const activeElement = computed(() => {
      return vptd.state.activeElement;
    });

    const { initmovement } = useMove(vptd, activeElement);

    const handleSelection = (e) => {
      var target = selectTarget(e.target);
      if (target) {
        var uuid = target.getAttribute("data-uuid");
        // 设置选中元素
        vptd.commit("select", {
          uuid: uuid || -1,
        });
        // 绑定移动事件：除背景图以外的元件才能移动
        target = activeElement.value;
        if (target.dragable) {
          initmovement(e); // 参见 mixins
        }
      } else {
        // 取消选中元素
        vptd.commit("select", {
          uuid: -1,
        });
      }
    };

    const selectTarget = (target) => {
      let type = target.getAttribute("data-type");
      if (type) {
        if (type === "viewport") {
          return false;
        } else {
          return target;
        }
      } else {
        return selectTarget(target.parentNode);
      }
    };

    onMounted(() => {
      // 采用事件代理的方式监听元件的选中操作
      let viewportDom = document.getElementById("viewport");
      if (viewportDom) {
        viewportDom.addEventListener("mousedown", handleSelection, false);
      } else {
        console.error("未找的‘viewport’节点");
      }

      // 绑定键盘上下左右键用于元件的移动
      document.addEventListener(
        "keydown",
        (e) => {
          e.stopPropagation();
          var target = activeElement.value;
          // 左
          if (e.keyCode === 37 && target.left) {
            target.left -= 1;
            return;
          }
          // 上
          if (e.keyCode === 38 && target.top) {
            e.preventDefault();
            target.top -= 1;
            return;
          }
          // 右
          if (e.keyCode === 39 && target.left) {
            target.left += 1;
            return;
          }
          // 下
          if (e.keyCode === 40 && target.top) {
            e.preventDefault();
            target.top += 1;
          }
        },
        true
      );
    });
    return {
      page,
      widgetStore,
      widgetId,
      backImg,
      handleSelection,
      selectTarget,
    };
  },
});
</script>

<style>
.holder {
  display: flex;
  justify-content: center;
  overflow: auto;
  font-size: 0;
  border: 1px solid #f5f5f5;
  border-width: 0 1px;
  background-image: linear-gradient(
      45deg,
      #f5f5f5 25%,
      transparent 0,
      transparent 75%,
      #f5f5f5 0
    ),
    linear-gradient(
      45deg,
      #f5f5f5 25%,
      transparent 0,
      transparent 75%,
      #f5f5f5 0
    );
  background-position: 0 0, 13px 13px;
  background-size: 26px 26px;
}
.screen {
  margin: 25px auto;
  transform-origin: center top;
  position: relative;
  box-shadow: 0 0 5px 1px #cccccc;
  background-color: #ffffff;
  background-repeat: no-repeat;
}
</style>
